#include "result.h"
#include "create.h"
#include "insert.h"
#include "select.h"
#include "update.h"
#include "delete.h"
#include "sqlite3.h"
using namespace std;

class Sqlite
{
protected:
	bool _isok;
	string lastsql;
	Result _result;
	struct sqlite3* _db;
	typedef int (*cb)(void*, int, char**, char**);
public:
	const bool& isok;
	const Result& result;
public:
	inline Sqlite(void);
	inline Sqlite(const string&);
	inline bool open(const string& fname);
	inline void close(void);
	inline bool exec(const string& sql, cb f=0, void*o=0, char**e=0);
	inline string errmsg(void)const;
	inline Sqlite& operator<<(const Create&);
	inline Sqlite& operator<<(const Insert&);
	inline Sqlite& operator<<(const Delete&);
	inline Sqlite& operator<<(const Update&);
	inline Sqlite& operator<<(const Select&);
	inline Sqlite& operator<<(const string&);
	
private:
	static int get(void* obj, int count, char **value, char **name);
	
};

inline Sqlite::Sqlite(void)
:_db(0),result(_result),_isok(0),isok(_isok)
{
}
inline Sqlite::Sqlite(const string& s)
:_db(0),result(_result),_isok(0),isok(_isok)
{
	open(s);
}

inline void Sqlite::close(void)
{
	if(_db)
	{
		sqlite3_close(_db);
		_db = 0;
		_isok = false;
		_result.clear();
	}
}
inline bool Sqlite::open(const string& fname)
{
	close();
	_isok = SQLITE_OK == sqlite3_open_v2
		(
			fname.data(),								//const char*			path
			&_db,										//struct sqlite3*		db
			SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,	//int					flags
			NULL										//struct sqlite3_vfs*	vfs
		);
	return _isok;
}
inline string Sqlite::errmsg(void)const
{
	if(_isok)
	{
		return "{" + lastsql + "} ok";
	}
	return "{" + lastsql + "} failed: " + sqlite3_errmsg(_db);
}
inline bool Sqlite::exec(const string& sql, cb f, void* o, char** e)
{
	_result.clear();
	lastsql = sql;
	_isok = (SQLITE_OK == sqlite3_exec(_db, sql.data(), f, o, e));
	return _isok;
}

inline Sqlite& Sqlite::operator<<(const Create& s)
{
	exec(s.data());
	return *this;
}
inline Sqlite& Sqlite::operator<<(const Insert& s)
{
	exec(s.data());
	return *this;
}
inline Sqlite& Sqlite::operator<<(const Delete& s)
{
	exec(s.data());
	return *this;
}
inline Sqlite& Sqlite::operator<<(const Update& s)
{
	exec(s.data());
	return *this;
}
inline Sqlite& Sqlite::operator<<(const Select& s)
{
	exec(s.data(), get, this);	
	return *this;
}
inline Sqlite& Sqlite::operator<<(const string& s)
{
	exec(s.data(), get, this);
	return *this;
}

inline int Sqlite::get(void* obj, int count, char **value, char **name)
{
	Sqlite& db = (*(Sqlite*)obj);

	db._result.get(count, name, value);

	return (count > 0 && name && value && *name && *value) ? 0 : -1;
}


